package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strconv"
)

func startServer() {
	http.HandleFunc("/svg", GetSVG)
	http.HandleFunc("/index", GetIndex)
	http.HandleFunc("/node", GetNode)
	http.HandleFunc("/update_node", WebUpdateNode)
	http.HandleFunc("/new_node", WebNewNode)
	http.HandleFunc("/swap_idx", WebSwapIndex)
	http.HandleFunc("/new_flow", NewFlow)
	http.HandleFunc("/alone", NodeIsAlone)
	http.HandleFunc("/del_node", NodeDelete)
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
	//err := http.ListenAndServeTLS("127.0.0.1:8443", "pems/new-cert.pem", "pems/new-key.pem", nil)
	err := http.ListenAndServe("127.0.0.1:8443", nil)
	log.Printf("server error:%v\n", err)
}

func main() {
	var f = flag.String("import", "", "[-import filename] import a toml file")
	flag.Parse()
	if *f != "" {
		ImportToml(*f)
		return
	}
	//chdir
	exe1, _ := os.Executable()
	dir1 := filepath.Dir(exe1)
	os.Chdir(dir1)
	//start server
	go startServer()
	browser, err := exec.LookPath("xdg-open")
	if err == nil {
		cmd1 := exec.Command(browser, "http://127.0.0.1:8443/index?flow=1")
		cmd1.Start()
	} else {
		log.Fatalln(err)
	}
	WaitSig()
	conn1.Close()
}

type DataIdx struct {
	Flow  string
	Flows []FlowInfo
}

func GetIndex(w http.ResponseWriter, r *http.Request) {
	t1, err1 := template.ParseFiles(path.Join("web", "svg.html"))
	if err1 != nil {
		log.Println(err1)
		return
	}
	flowID := r.URL.Query().Get("flow")
	var map1 = new(DataIdx)
	map1.Flow = flowID
	map1.Flows = GetFlows()
	w.WriteHeader(200)
	err1 = t1.Execute(w, map1)
	if err1 != nil {
		log.Println(err1)
	}
}

func GetSVG(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	flowID, err := strconv.Atoi(r.FormValue("flow"))
	if err != nil {
		w.WriteHeader(404)
		log.Printf("get svg atoi flow:%v\n", err)
		return
	}
	h1 := w.Header()
	h1.Set("Content-Type", "image/svg+xml")
	w.WriteHeader(200)
	ShowSVG(flowID, w)
}

func GetNode(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	flowID, err := strconv.Atoi(r.FormValue("flow"))
	if err != nil {
		w.WriteHeader(404)
		log.Printf("get node atoi flow:%v\n", err)
		return
	}
	nodeID, err := strconv.Atoi(r.FormValue("node"))
	if err != nil {
		w.WriteHeader(404)
		log.Printf("atoi node:%v\n", err)
		return
	}
	res := GetNodeInfo(flowID, nodeID)
	if res == nil {
		w.WriteHeader(404)
		log.Printf("getnodeinfo:%v\n", err)
		return
	}
	json1, err := json.Marshal(res)
	if err != nil {
		w.WriteHeader(404)
		log.Printf("json marshal:%v\n", err)
		return
	}
	w.WriteHeader(200)
	w.Write(json1)
}

func WebUpdateNode(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	json1 := r.FormValue("json")
	var node1 NodeInfo
	err := json.Unmarshal([]byte(json1), &node1)
	if err != nil {
		w.WriteHeader(404)
		log.Printf("json unmarshal:%v\n", err)
		return
	}
	flow := r.FormValue("flow")
	tblName := fmt.Sprintf("flow%s", flow)
	err = UpdateNode(tblName, node1.Id, node1.Name, node1.Status, node1.Depend)
	if err != nil {
		w.WriteHeader(404)
		log.Printf("UpdateNode:%v\n", err)
		return
	}
	http.Redirect(w, r, fmt.Sprintf("/index?flow=%s", flow), http.StatusFound)
}

func WebNewNode(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	json1 := r.FormValue("json")
	var node1 NodeInfo
	err := json.Unmarshal([]byte(json1), &node1)
	if err != nil {
		w.WriteHeader(404)
		log.Printf("json unmarshal:%v\n", err)
		return
	}
	flow := r.FormValue("flow")
	tblName := fmt.Sprintf("flow%s", flow)
	err = InsertNode(tblName, node1.Name, node1.Status, node1.Depend)
	if err != nil {
		w.WriteHeader(404)
		log.Printf("NewNode:%v\n", err)
		return
	}
	http.Redirect(w, r, fmt.Sprintf("/index?flow=%s", flow), http.StatusFound)
}

func WebSwapIndex(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	id1, err := strconv.Atoi(r.FormValue("id1"))
	if err != nil {
		w.WriteHeader(404)
		log.Printf("atoi id1:%v\n", err)
		return
	}
	id2, err := strconv.Atoi(r.FormValue("id2"))
	if err != nil {
		w.WriteHeader(404)
		log.Printf("atoi id2:%v\n", err)
		return
	}
	flow := r.FormValue("flow")
	tblName := fmt.Sprintf("flow%s", flow)
	err = SwapIndex(tblName, id1, id2)
	if err != nil {
		w.WriteHeader(404)
		log.Printf("swap index:%v\n", err)
		return
	}
	http.Redirect(w, r, fmt.Sprintf("/index?flow=%s", flow), http.StatusFound)
}

func NewFlow(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	name := r.FormValue("flow")
	if len(name) == 0 {
		w.WriteHeader(404)
		log.Println("argument 'flow' not exist.")
		return
	}
	id, err := CreateFlow(name)
	if err != nil {
		w.WriteHeader(404)
		log.Printf("CreateFlow error:%v\n", err)
		return
	}
	http.Redirect(w, r, fmt.Sprintf("/index?flow=%d", id), http.StatusFound)
}

//NodeIsAlone ajax json response
func NodeIsAlone(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	flowID, err := strconv.Atoi(r.FormValue("flow"))
	if err != nil {
		w.WriteHeader(404)
		log.Printf("NodeIsAlone atoi error:%v\n", err)
		return
	}
	nodeID, err := strconv.Atoi(r.FormValue("node"))
	if err != nil {
		w.WriteHeader(404)
		log.Printf("NodeIsAlone atoi error:%v\n", err)
		return
	}
	w.WriteHeader(200)
	if IsAlone(flowID, nodeID) {
		w.Write([]byte(fmt.Sprintf("{\"flow\":%d,\"node\":%d,\"alone\":true}", flowID, nodeID)))
	} else {
		w.Write([]byte(fmt.Sprintf("{\"flow\":%d,\"node\":%d,\"alone\":false}", flowID, nodeID)))
	}
}

func NodeDelete(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	flowID, err := strconv.Atoi(r.FormValue("flow"))
	if err != nil {
		w.WriteHeader(404)
		log.Printf("NodeIsAlone atoi error:%v\n", err)
		return
	}
	nodeID, err := strconv.Atoi(r.FormValue("node"))
	if err != nil {
		w.WriteHeader(404)
		log.Printf("NodeIsAlone atoi error:%v\n", err)
		return
	}
	err = DelNode(flowID, nodeID)
	if err != nil {
		w.WriteHeader(404)
		log.Printf("NodeIsAlone atoi error:%v\n", err)
		return
	} else {
		http.Redirect(w, r, fmt.Sprintf("/index?flow=%d", flowID), http.StatusFound)
	}
}
